<template>
  <div class="agv-map-container">
    <!-- 地图容器 -->
    <div ref="mapContainer" class="map-container">
      <!-- 地图控制区 -->
      <div class="map-controls">
        <n-button @click="toggleFullscreen" size="small" class="control-btn">
          <n-icon>
            <Icons.Expand />
          </n-icon>
        </n-button>
        <n-button @click="resetView" size="small" class="control-btn">
          <n-icon>
            <Icons.Refresh />
          </n-icon>
        </n-button>
        <n-button @click="togglePanel" size="small" class="control-btn">
          <n-icon>
            <Icons.List />
          </n-icon>
        </n-button>
      </div>

      <!-- AGV状态面板 -->
      <div ref="agvStatusPanel" class="agv-status-panel" :style="{ display: isPanelVisible ? 'block' : 'none' }">
        <n-card title="AGV状态监控" size="small" hoverable closable @close="handleClose">
          <n-list v-if="agvList.length > 0">
            <n-list-item v-for="agv in agvList" :key="agv.car_index">
              <template #prefix>
                <div class="agv-indicator" :style="{ backgroundColor: getAgvColor(agv.status) }"></div>
              </template>
              <template #default>
                {{ agv.car_index }}号 - {{ getStatusText(agv.status) }} 电量: {{ agv.battery }}%
              </template>
              <template #suffix>
                <div class="agv-indicator" :style="{ backgroundColor: getAgvColor(agv.status) }"></div>
              </template>
            </n-list-item>
          </n-list>
          <div v-else class="empty-state">暂无AGV数据</div>
        </n-card>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, reactive, watch } from 'vue';
import * as L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import 'leaflet-ant-path';
import { NButton, NCard, NList, NListItem, NIcon, useMessage } from 'naive-ui';
import * as Icons from '@vicons/ionicons5';
import { API_URLS } from '../../utils/apiConfig';
import axios from 'axios';


/** 全局类型定义
 * @typedef {Object} AGVInfo
 * @property {number} car_index - AGV编号
 * @property {string} status - AGV状态
 * @property {number} battery - 电量
 * @property {number} x - X坐标
 * @property {number} y - Y坐标
 * @property {number} [start_x] - 起点X坐标
 * @property {number} [start_y] - 起点Y坐标
 * @property {number} [end_x] - 终点X坐标
 * @property {number} [end_y] - 终点Y坐标
 */

/**
 * @typedef {Object} StationInfo
 * @property {string} name - 库位名称
 * @property {string} type - 库位类型
 * @property {string} status - 库位状态
 * @property {number} x - X坐标
 * @property {number} y - Y坐标
 */

/** 地图相关变量
 */
const mapContainer = ref(null);
const agvStatusPanel = ref(null);
let map = null;
let agvMarkers = {}; // 存储AGV标记点
let pathLayers = {}; // 存储路径图层
let stationMarkers = {}; // 存储库位标记

// 面板显示状态
const isPanelVisible = ref(false);
const message = useMessage();

// 数据列表
const agvList = reactive([]);
const stationList = reactive([]);
const edgeList = reactive([]);
const nodeList = reactive([]);

// 地图尺寸常量
const MAP_CONFIG = {
  bound_width: 1600,
  bound_height: 900,
  minZoom: 0,
  maxZoom: 5,
  gridSize: 50,
  center: { x: 1600 / 2, y: 900 / 2 },
  initialZoom: 1
};

// AGV状态配置
const AGV_STATUS_CONFIG = {
  running: { color: '#4CAF50', text: '运行中' },
  idle: { color: '#2196F3', text: '空闲' },
  error: { color: '#F44336', text: '故障' },
  charging: { color: '#FFC107', text: '充电中' },
  default: { color: '#9E9E9E', text: '未知' }
};

// 辅助函数: 获取AGV状态对应的颜色
const getAgvColor = (status) => {
  return AGV_STATUS_CONFIG[status]?.color || AGV_STATUS_CONFIG.default.color;
};

// 辅助函数: 获取AGV状态文本
const getStatusText = (status) => {
  return AGV_STATUS_CONFIG[status]?.text || AGV_STATUS_CONFIG.default.text;
};

/**创建自定义网格底图
 * @returns {L.GridLayer} 网格图层
 */
const createGridLayer = () => {
  const gridLayer = L.gridLayer({
    attribution: 'Custom Grid'
  });
  
  gridLayer.createTile = function (coords) {
    const tile = document.createElement('canvas');
    const size = this.getTileSize();
    tile.width = size.x;
    tile.height = size.y;
    
    const ctx = tile.getContext('2d');
    ctx.strokeStyle = '#c0c0c0';
    ctx.lineWidth = 1;
    
    // 绘制垂直线
    for (let x = 0; x <= size.x; x += MAP_CONFIG.gridSize) {
      ctx.beginPath();
      ctx.moveTo(x, 0);
      ctx.lineTo(x, size.y);
      ctx.stroke();
    }
    
    // 绘制水平线
    for (let y = 0; y <= size.y; y += MAP_CONFIG.gridSize) {
      ctx.beginPath();
      ctx.moveTo(0, y);
      ctx.lineTo(size.x, y);
      ctx.stroke();
    }
    
    return tile;
  };
  
  return gridLayer;
};

/** 添加边界线 */
const addBoundaryLines = () => {
  if (!map) return;
  
  // 绘制地图边界线（仅显示边界线，无内部填充）
  L.polygon([
    [0, 0],
    [MAP_CONFIG.bound_height, 0],
    [MAP_CONFIG.bound_height, MAP_CONFIG.bound_width],
    [0, MAP_CONFIG.bound_width]
  ]).addTo(map).setStyle({
    color: '#FF0000',
    weight: 2,
    opacity: 0.5,
    fillOpacity: 0, // 设置填充透明度为0，不显示内部颜色填充
    fillColor: 'transparent' // 明确设置填充颜色为透明
  });
};

/** 初始化地图
 */
const initMap = () => {
  if (!mapContainer.value) return;
  
  // 创建自定义坐标系 (以米为单位)
  const customCRS = L.CRS.Simple;

  // 地图边界 - 根据厂区实际尺寸调整
  const bounds = [[0, 0], [MAP_CONFIG.bound_height, MAP_CONFIG.bound_width]];

  // 初始化地图
  map = L.map(mapContainer.value, {
    crs: customCRS,
    minZoom: MAP_CONFIG.minZoom,
    maxZoom: MAP_CONFIG.maxZoom,
    maxBounds: bounds,
    maxBoundsViscosity: 0.5,
    attributionControl: false
  }).setView([MAP_CONFIG.center.y, MAP_CONFIG.center.x], MAP_CONFIG.initialZoom);

  // 添加网格图层到地图
  createGridLayer().addTo(map);
  
  // 添加边界线
  addBoundaryLines();

  // 添加比例尺
  L.control.scale({
    imperial: false,
    maxWidth: 100,
    unit: 'm'
  }).addTo(map);
};

/** 创建AGV图标
 * @param {string} status - AGV状态
 * @returns {L.Icon} Leaflet图标对象
 */
const createAgvIcon = (status) => {
  return new L.Icon({
    iconUrl: `/src/assets/agv/agv_car_${status}.svg`,
    className: 'agv-marker',
    iconSize: [36, 36],
    iconAnchor: [18, 18]
  });
};

/** 创建库位图标
 * @param {string} status - 库位状态
 * @returns {L.Icon} Leaflet图标对象
 */
const createStationIcon = (status) => {
  return new L.Icon({
    iconUrl: `/src/assets/agv/station_${status}.svg`,
    className: 'station-marker',
    iconSize: [50, 50],
    iconAnchor: [25, 25]
  });
};

/** 初始化AGV标记
 */
const initAgvMarkers = () => {
  if (!map) return;
  
  agvList.forEach(agv => {
    addOrUpdateAgvMarker(agv);
  });
};

/** 添加或更新单个AGV标记
 * @param {AGVInfo} agv - AGV信息
 */
const addOrUpdateAgvMarker = (agv) => {
  if (!map) return;
  
  const { car_index, x, y, status, battery } = agv;
  
  // 如果标记已存在，更新位置和图标
  if (agvMarkers[car_index]) {
    const marker = agvMarkers[car_index];
    marker.setLatLng([y, x]);
    
    // 更新图标和弹窗内容
    marker.setIcon(createAgvIcon(status));
    marker.bindPopup(`
      <div class="agv-popup">
        <h3>${car_index}</h3>
        <p>状态: ${getStatusText(status)}</p>
        <p>电量: ${battery}%</p>
        <p>位置: (${x}, ${y})</p>
      </div>
    `);
  } else {
    // 创建新标记
    const marker = L.marker([y, x], { icon: createAgvIcon(status) }).addTo(map);
    
    // 添加AGV信息弹窗
    marker.bindPopup(`
      <div class="agv-popup">
        <h3>${car_index}</h3>
        <p>状态: ${getStatusText(status)}</p>
        <p>电量: ${battery}%</p>
        <p>位置: (${x}, ${y})</p>
      </div>
    `);
    
    agvMarkers[car_index] = marker;
  }
};

/** 初始化路径
 */
const initRoutes = () => {
  if (!map) return;

  edgeList.forEach(edge => {
    // const pathLayer = pathLayers[edge.id];
    const { start_x, start_y, end_x, end_y, status } = edge;
    const pathPoints = [[start_y, start_x], [end_y, end_x]];

    // 创建路径 (使用ant-path插件实现流动效果)
    const pathLayer = L.polyline(pathPoints, {
      color: '#000000',
      weight: 2, // 路径宽度
      opacity: 0.7, // 路径透明度
      interactive: false,
    }).addTo(map);
    
  });
};

/** 添加或更新单个AGV路径
 * @param {AGVInfo} agv - AGV信息
 */
const addOrUpdateAgvRoute = (agv) => {
  if (!map || !agv.start_x || !agv.start_y || !agv.end_x || !agv.end_y) return;
  
  const { car_index, start_x, start_y, end_x, end_y, status } = agv;
  
  // 转换路径点格式以适应Leaflet
  const pathPoints = [[start_y, start_x], [end_y, end_x]];
  
  // 如果路径已存在，更新路径点位置和样式
  if (pathLayers[car_index]) {
    const pathLayer = pathLayers[car_index];
    // 更新路径点位置
    pathLayer.setLatLngs(pathPoints);
    // 更新样式
    pathLayer.setStyle({
      color: getAgvColor(status)
    });
  } else {
    // 创建动态路径 (使用ant-path插件实现流动效果)
    const pathLayer = L.polyline.antPath(pathPoints, {
      color: getAgvColor(status),
      weight: 4,
      opacity: 0.7,
      dashArray: [10, 20],
      delay: 300
    }).addTo(map);
    
    pathLayers[car_index] = pathLayer;
  }
};

/** 初始化库位标记
 */
const initStations = () => {
  if (!map) return;
  
  // 清除现有库位标记和标签
  Object.values(stationMarkers).forEach(markerObj => {
    if (markerObj.marker) {
      map.removeLayer(markerObj.marker);
    }
    if (markerObj.labelMarker) {
      map.removeLayer(markerObj.labelMarker);
    }
  });
  stationMarkers = {};
  
  stationList.forEach(station => {
    const { name, type, status, x, y } = station;
    const marker = L.marker([y, x], { icon: createStationIcon(status) }).addTo(map);
    
    // 添加库位名称标签 - 使用自定义HTML元素
    const label = L.divIcon({
      html: `<div class="station-label">${name}</div>`,
      className: 'station-label-container',
      iconSize: [80, 20],
      interactive: false,
      iconAnchor: [40, 15] // 位置调整，使其显示在图标下方
    });
    
    // 创建标签标记并添加到地图
    const labelMarker = L.marker([y, x], { icon: label }).addTo(map);
    
    // 添加库位信息弹窗
    marker.bindPopup(`
      <div class="station-popup">
        <h3>${name}</h3>
        <p>类型: ${type}</p>
        <p>状态: ${status}</p>
        <p>位置: (${x}, ${y})</p>
      </div>
    `);
    
    // 存储标记和标签，方便后续管理
    stationMarkers[name] = { marker, labelMarker };
  });
};

/** 创建节点图标
 */
const initNodes = () => {
  if (!map) return;
  
  nodeList.forEach(node => {
    const { id, x, y } = node;

    L.circleMarker([y, x], {
      color: '#000000',
      fillColor: '#000000',
      fillOpacity: 0.5, // 填充透明度


      opacity: 0.7, // 路径透明度
      weight: 0.5, // 路径宽度
      interactive: false,
      radius: 5 // 节点半径
    }).addTo(map);
    
  });
};

/** 获取所有虚拟AGV列表数据
 */
const fetchAGVList = async () => {
  try {
    const response = await axios.get(API_URLS.agv.position, { params: { page: 1, page_size: 1000 } });

    if (response.data.code === 200 && response.data.data) {
      // 清空原数组并添加新数据，保持响应式
      agvList.length = 0;
      response.data.data.forEach(item => {
        agvList.push(item);
      });
    } else {
      message.error(`获取数据失败: ${response.data.msg || "未知错误"}`);
    }
  } catch (err) {
    message.error(`网络错误: 无法连接到服务器 (${err.message})`);
  }
};

/** 获取所有地图边列表数据
 * @description: 获取所有地图边列表数据
 */
const fetchEdgeList = async () => {
  try {
    const response = await axios.get(API_URLS.map_edge.lineList, { params: {} });
    if (response.data.code === 200 && response.data.data) {
      // 清空原数组并添加新数据，保持响应式
      edgeList.length = 0;
      response.data.data.forEach(item => {
        edgeList.push(item);
      });
      // 当真实数据加载完成后，更新地图上的路径
      initRoutes();
    } else {
      message.error(`获取数据失败: ${response.data.msg || "未知错误"}`);
    }
  } catch (err) {
    message.error(`网络错误: 无法连接到服务器 (${err.message})`);
  }
};

 /** 获取所有站点数据
 * @description: 获取所有站点数据
 */
const fetchStationList = async () => {
  try {
    const response = await axios.get(API_URLS.map_node.all, { params: {} });
    if (response.data.code === 200 && response.data.data) {
      // 清空原数组并添加新数据，保持响应式
      stationList.length = 0;
      response.data.data.forEach(item => {
        stationList.push(item);
      });
      // 当真实数据加载完成后，更新地图上的库位标记
      initStations();
    } else {
      message.error(`获取数据失败: ${response.data.msg || "未知错误"}`);
    }
  } catch (err) {
    message.error(`网络错误: 无法连接到服务器 (${err.message})`);
  }
};

/** 获取所有节点列表数据
 */
const fetchNodeList = async () => {
  try {
    const response = await axios.get(API_URLS.map_node.node, { params: {} });
    if (response.data.code === 200 && response.data.data) {
      // 清空原数组并添加新数据，保持响应式
      nodeList.length = 0;
      response.data.data.forEach(item => {
        nodeList.push(item);
      });
      // 当真实数据加载完成后，更新地图上的节点标记
      initNodes();
    } else {
      message.error(`获取数据失败: ${response.data.msg || "未知错误"}`);
    }
  } catch (err) {
    message.error(`网络错误: 无法连接到服务器 (${err.message})`);
  }
};

/** 更新AGV标记和路径
 */
const updateAgvMarkersAndRoutes = () => {
  if (!map) return;
  
  // 获取当前存在的AGV ID集合
  const currentAgvIds = new Set(agvList.map(agv => agv.car_index));
  
  // 移除不再存在的AGV标记和路径
  Object.keys(agvMarkers).forEach(id => {
    if (!currentAgvIds.has(parseInt(id))) {
      map.removeLayer(agvMarkers[id]);
      delete agvMarkers[id];
      
      if (pathLayers[id]) {
        map.removeLayer(pathLayers[id]);
        delete pathLayers[id];
      }
    }
  });
  
  // 更新或添加AGV标记和路径
  agvList.forEach(agv => {
    addOrUpdateAgvMarker(agv);
    addOrUpdateAgvRoute(agv);
  });
};

/** 模拟AGV移动
 */
const simulateAgvMovement = () => {
  // 每5秒更新一次数据，避免过于频繁的网络请求
  const interval = setInterval(async () => {
    await fetchAGVList();
  }, 2000);

  return interval;
};

/** 重置地图视图
 */
const resetView = () => {
  if (map) {
    map.setView([MAP_CONFIG.center.y, MAP_CONFIG.center.x], MAP_CONFIG.initialZoom);
  }
};

/** 切换全屏地图
 */
const toggleFullscreen = () => {
  const container = mapContainer.value;
  if (!container) return;
  
  if (!document.fullscreenElement) {
    container.requestFullscreen().catch(err => {
      console.error(`全屏错误: ${err.message}`);
      message.error(`全屏切换失败: ${err.message}`);
    });
  } else {
    document.exitFullscreen();
  }
};

/** 切换AGV状态面板显示
 */
const togglePanel = () => {
  isPanelVisible.value = !isPanelVisible.value;
};

/** 关闭AGV状态面板
 */
const handleClose = () => {
  isPanelVisible.value = false;
};

// 生命周期钩子
let movementInterval;

//组件挂载时初始化
onMounted(() => {
  initMap();
  fetchEdgeList();
  fetchNodeList();
  fetchStationList();
  fetchAGVList();
  isPanelVisible.value = false; // 初始化时关闭面板
  movementInterval = simulateAgvMovement();
});

//组件卸载时清理资源
onUnmounted(() => {
  // 清理资源
  if (map) {
    map.remove();
    map = null;
  }
  
  if (movementInterval) {
    clearInterval(movementInterval);
  }
  
  // 清空引用
  agvMarkers = {};
  pathLayers = {};
  stationMarkers = {};
});

// 监听AGV数据变化，更新UI
watch(agvList, (newVal) => {
  if (newVal.length > 0) {
    updateAgvMarkersAndRoutes();
  }
}, { deep: true });

</script>

<style scoped>
.agv-map-container {
  padding: 10px;
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  box-sizing: border-box;
}

.map-container {
  width: 100%;
  height: 100%;
}

.map-controls {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.control-btn {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(18, 187, 150, 0.755);
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.control-btn:hover {
  background-color: rgba(193, 241, 103, 0.593);
}

.agv-status-panel {
  position: absolute;
  top: 10px;
  right: 100px;
  z-index: 1000;
  width: 300px;
  transition: all 0.3s ease;
}

/* 空状态样式 */
.empty-state {
  text-align: center;
  color: #999;
  padding: 20px;
}

/* AGV标记样式 */
.agv-marker {
  transform: translate(-50%, -50%);
  transition: transform 0.3s ease;
}

.agv-marker:hover {
  transform: translate(-50%, -50%) scale(1.1);
}

.agv-icon {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: bold;
  font-size: 12px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
}

/* 库位标记样式 */
.station-marker {
  transform: translate(-50%, -50%);
  transition: transform 0.3s ease;
}

.station-marker:hover {
  transform: translate(-50%, -50%) scale(1.1);
}

.station-icon {
  background-color: rgba(33, 150, 243, 0.8);
  color: white;
  padding: 3px 10px;
  border-radius: 4px;
  font-size: 12px;
  text-align: center;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}

/* 弹窗样式 */
.agv-popup,
.station-popup {
  min-width: 150px;
}

.agv-popup h3,
.station-popup h3 {
  margin: 0 0 5px 0;
  font-size: 14px;
}

.agv-popup p,
.station-popup p {
  margin: 2px 0;
  font-size: 12px;
}

/* AGV状态指示器 */
.agv-indicator {
  width: 12px;
  height: 12px;
  border-radius: 50%;
}

/* AGV状态指示器 */
.node-indicator {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background-color: rgba(0, 0, 0, 0.7);
}

/* 库位标签样式 */
.station-label-container {
  transform: translate(-50%, 0);
  pointer-events: none; /* 防止标签影响点击交互 */
}

.station-label {
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 2px 8px;
  border-radius: 3px;
  font-size: 12px;
  white-space: nowrap;
  text-align: center;
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 全屏样式 */
.agv-map-container:fullscreen {
  padding: 0;
}

.agv-map-container:fullscreen .map-container {
  width: 100%;
  height: 100vh;
}

</style>
